# -*- coding: utf-8 -*-
import aiosqlite

from src       import utils
from src.types import Region, Weather

from fastapi           import Request, APIRouter, HTTPException
from fastapi.responses import Response, JSONResponse


region = APIRouter(prefix = "/region", dependencies = [utils.check.has_auth()])


@region.get("/array")
async def regions_get(request: Request):
    database: aiosqlite.Connection = request.app.database

    cursor = await database.execute("SELECT * FROM regions")
    result = await cursor.fetchall()
    column = ('id', 'name', 'parentRegion', 'regionType', 'latitude', 'longitude', 'accountId')

    regions = []

    for region in result:
        dictionary = {}

        for index, value in enumerate(region):
            dictionary[column[index]] = value
        
        regions.append(dictionary)

    return JSONResponse(regions, status_code = 200)


@region.get("/{regionId}")
async def region_get(request: Request, regionId: int):
    if regionId == None or 0 >= regionId:
        raise HTTPException(400, detail = "Invalid ID")

    region = await Region.get_by(request.app.database, id = regionId)

    if not region:
        raise HTTPException(404, detail = "The region with this ID was not found")
    return JSONResponse(region("id", "regionType", "accountId", "name", "parentRegion", "latitude", "longitude"), status_code = 200)


@region.post("/")
async def region_add(request: Request):
    data: dict  = await utils.parse.dictionary(request = request)
    keys: tuple = ("name", "latitude", "longitude")

    if not data:
        raise HTTPException(400, detail = "Failed to get passed values, specify them in JSON format")

    if (missing := [key for key in keys if (key not in data) or data[key] == None]) != []:
        raise HTTPException(400, detail = f"No values found: {', '.join(missing)}")

    database: aiosqlite.Connection = request.app.database

    exists = await Region.exists(database, latitude = data['latitude'], longitude = data['longitude'])

    if exists:
        raise HTTPException(409, detail = 'The region with current "longitude" and "latitude" already exists')

    region = await Region.create(request.app.database, accountld = int(request.cookies.get("id")), **data)
    return JSONResponse(region("id", "name", "parentRegion", "regionType", "latitude", "longitude"), status_code = 201)


@region.put("/{regionId}")
async def region_change(request: Request, regionId: int):
    if regionId == None or 0 >= regionId:
        raise HTTPException(400, detail = "Invalid ID")

    data = await utils.parse.dictionary(request)

    if not data:
        raise HTTPException(400, detail = "Failed to get passed values, specify them in JSON format")

    region = await Region.get_by(request.app.database, id = regionId)

    if not region:
        raise HTTPException(404, detail = "The region with this ID was not found")

    for key in ("name", "latitude", "longitude"):
        if data.get(key) == None:
            raise HTTPException(400, detail = f"Missing or invalid {key}")

    if region.latitude != data["latitude"] or region.longitude != data["longitude"]:
        exists = await region.exists(latitude = data['latitude'], longitude = data['longitude'])

        if exists:
            raise HTTPException(409, detail = 'The region with current "longitude" and "latitude" already exists')

    await region.update(accountId = int(request.cookies.get("id")), **data)
    return JSONResponse(region("id", "name", "parentRegion", "latitude", "longitude"), status_code = 200)


@region.delete("/{regionId}")
async def region_delete(request: Request, regionId: int):
    if regionId == None or 0 >= regionId:
        raise HTTPException(400, detail = "Invalid ID")

    region = await Region.get_by(request.app.database, id = regionId)

    if not region:
        raise HTTPException(404, detail = "The region with this ID was not found")

    await region.delete()
    return Response(None)


@region.post("/{regionId}/weather/{weatherId}")
async def region_add_weather_by_region(request: Request, regionId: int, weatherId: int):
    if regionId == None or 0 >= regionId:
        raise HTTPException(400, detail = "Invalid regionID")

    if weatherId == None or 0 >= weatherId:
        raise HTTPException(400, detail = "Invalid weatherId")

    db     = request.app.database
    region = await Region.get_by(db, id = regionId)

    if not region:
        raise HTTPException(404, detail = "The region with this ID was not found")

    weather = await Weather.get_by(db, id = weatherId)

    if not weather:
        raise HTTPException(404, detail = "The weather with this ID was not found")

    await weather.update({
        "regionId":   region.id,
        "regionName": region.name
    })

    return JSONResponse({
        "id":                  regionId,
        "regionName":          region.name,
        "temperature":         weather.temperature,
        "humidity":            weather.humidity,
        "windSpeed":           weather.windSpeed,
        "weatherCondition":    weather.weatherCondition,
        "precipitationAmount": weather.precipitationAmount,
        "measurementDateTime": weather.measurementDateTime,
        "weatherForecast":     weather.weatherForecast
    })


@region.delete("/{regionId}/weather/{weatherId}")
async def region_delete_weather_by_region(request: Request, regionId: int, weatherId: int):
    if regionId == None or 0 >= regionId:
        raise HTTPException(400, detail = "Invalid regionID")

    if weatherId == None or 0 >= weatherId:
        raise HTTPException(400, detail = "Invalid weatherId")

    db     = request.app.database
    region = await Region.get_by(db, id = regionId)

    if not region:
        raise HTTPException(404, detail = "The region with this ID was not found")

    weather = await Weather.get_by(db, id = weatherId)

    if not weather:
        raise HTTPException(404, detail = "The weather with this ID was not found")

    if weather.regionId != region.id:
        raise HTTPException(400, detail = "The weather does not belong to the region")

    await weather.delete()
    return JSONResponse(region("id", "name", "parentRegion", "latitude", "longitude"))
